package jp.co.dailyReport.workItem;

import java.util.ArrayList;
import java.util.Vector;
import java.sql.SQLException;
import org.apache.log4j.Logger;
import jp.co.dailyReport.ExecuterManager;
import jp.co.dailyReport.ConnectionFactory;
import jp.co.dailyReport.DataUnavailableException;
import jp.co.dailyReport.staff.Staff;
import jp.co.dailyReport.PermissionManager;
import jp.co.dailyReport.project.PjStaff;
import jp.co.dailyReport.project.PjStaffManager;
import jp.co.dailyReport.workItem.sql.WorkItemDeleteExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemLoadExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemInsertExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemLoadMaxDisplayNmExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemLoadMaxIDExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemPIdLoadExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemsLoadExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemUpdateExecuter;
import jp.co.dailyReport.workItem.sql.WorkItemWeeklyReportInsertExecuter;

/**
 * 作業項目情報管理クラス
 */
public class WorkItemManager {

	private static Logger log = Logger.getLogger(WorkItemManager.class);

	/**
	 * 作業項目情報を取得します。
	 * 
	 * @return 作業項目オブジェクトの配列
	 * @throws DataUnavailableException
	 */
	public static WorkItem[] load() throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemsLoadExecuter workItemsLoadExecuter = new WorkItemsLoadExecuter();
		Object objs[] = (Object[])null;

		try {
			objs = ExecuterManager.execute(connectionFactory, workItemsLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
			return new WorkItem[0];
		} else {
			return (WorkItem[])objs;
		}
	}

	/**
	 * 社員の権限で処理に応じて指定操作可能な作業項目情報を取得します。
	 * 
	 * @param staff 社員オブジェクト
	 * @param methodId 操作方法ID(PermissionManagerで定義)
	 * @param operationId 業務ID(PermissionManagerで定義)
	 * @return 作業項目オブジェクトの配列
	 * @throws DataUnavailableException
	 */
	public static WorkItem[] load(Staff staff,int operationId,int methodId)
		 throws DataUnavailableException {

		WorkItem[] workItems = load();
		ArrayList answer = new ArrayList();
		if(PermissionManager.hasPermission(staff,operationId,methodId)){
			//ｱﾙﾊﾞｲﾄ、外注
			if(staff.getEmploymentSystem() != Integer.parseInt(Staff.STAFF_EMPLOYMENTSYSTEM_ID[2])){
				PjStaff[] pjStaff = PjStaffManager.getProjectId(staff.getStaffId());
				for(int i =0; i < pjStaff.length;i++){
					WorkItem[] workItemList = loadPId(pjStaff[i].getProjectId());
					for(int j =0; j < workItemList.length;j++){
						answer.add(workItemList[j]);
					}
				}
			} else {
				for(int i =0; i < workItems.length;i++){
					answer.add(workItems[i]);
				}
			}
		}
		return (WorkItem[])answer.toArray(new WorkItem[0]);
	}

	/**
	 * 作業項目情報を取得します。
	 * 
	 * @param workItemId 作業項目ID
	 * @return 作業項目オブジェクト
	 * @throws DataUnavailableException
	 */
	public static WorkItem load(int workItemId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemLoadExecuter workItemLoadExecuter = new WorkItemLoadExecuter(workItemId);
		Object objs[] = (Object[])null;

		try {
			objs = ExecuterManager.execute(connectionFactory, workItemLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
			return new WorkItem();
		} else {
			return (WorkItem)objs[0];
	    }
	}

	/**
	 * 作業項目情報を取得します。
	 * 
	 * @param projectId プロジェクトID
	 * @return 作業項目オブジェクトの配列
	 * @throws DataUnavailableException
	 */
	public static WorkItem[] loadPId(int projectId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemPIdLoadExecuter workItemPIdLoadExecuter = new WorkItemPIdLoadExecuter(projectId);
		Object objs[] = (Object[])null;

		try {
			objs = ExecuterManager.execute(connectionFactory, workItemPIdLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
			return new WorkItem[0];
		} else {
			return (WorkItem[])objs;
	    }
	}

	/**
	 * 作業項目情報を取得します。
	 * 
	 * @param projectId プロジェクトID
	 * @param staffId 社員ID
	 * @return 作業項目オブジェクトの配列
	 * @throws DataUnavailableException
	 */
	public static WorkItem[] load(int projectId,int staffId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemPIdLoadExecuter workItemPIdLoadExecuter = new WorkItemPIdLoadExecuter(projectId);
		Object objs[] = (Object[])null;
		Vector workItemList = new Vector();

		try {
			objs = ExecuterManager.execute(connectionFactory, workItemPIdLoadExecuter);
		} catch(SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if(objs == null || objs.length == 0) {
			return new WorkItem[0];
		} else {
			WorkItem[] workItem = (WorkItem[])objs;
			for(int i=0;i<workItem.length;i++){
				if(workItem[i].getAddStaffId()==0 || workItem[i].getAddStaffId()==staffId){
					workItemList.add(workItem[i]);	
				}
			}
			return (WorkItem[])workItemList.toArray(new WorkItem[0]);
		}
	}

	/**
	 * 作業項目IDの最大値を取得します。
	 * 
	 * @return 作業項目IDの最大値
	 * @throws DataUnavailableException
	 */
	public static int loadMaxID() throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemLoadMaxIDExecuter workItemLoadMaxIDExecuter = new WorkItemLoadMaxIDExecuter();
		Object objs[] = (Object[]) null;

		try {
			objs = ExecuterManager.execute(connectionFactory, workItemLoadMaxIDExecuter);
		} catch (SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if (objs == null || objs.length == 0) {

			return 0;
		} else {
			return Integer.parseInt((String) objs[0]);
		}
	}

	/**
	 * 作業項目の表示番号の最大値を取得します。
	 * 
	 * @param projectId プロジェクトID
	 * @return 作業項目の表示番号
	 * @throws DataUnavailableException
	 */
	public static int loadMaxDisplayNm(int projectId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemLoadMaxDisplayNmExecuter workItemLoadMaxDisplayNmExecuter = new WorkItemLoadMaxDisplayNmExecuter(projectId);
		Object objs[] = (Object[]) null;

		try {
			objs = ExecuterManager.execute(connectionFactory, workItemLoadMaxDisplayNmExecuter);
		} catch (SQLException sqle) {
			throw new DataUnavailableException(sqle.toString());
		}
		if (objs == null || objs.length == 0) {

			return 0;
		} else {
			return Integer.parseInt((String) objs[0]);
		}
	}

	/**
	 * 作業項目情報を更新します。
	 * 
	 * @param workItem 作業項目オブジェクト
	 * @throws DataUnavailableException
	 */
	public static void update(WorkItem workItem) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemUpdateExecuter workItemUpdateExecuter = new WorkItemUpdateExecuter(workItem);

		try {
			ExecuterManager.execute(connectionFactory, workItemUpdateExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 作業項目情報を登録します。(プロジェクト登録ページ)
	 * 
	 * @param workItem 作業項目オブジェクト
	 * @throws DataUnavailableException
	 */
	public static void insert(WorkItem workItem) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemInsertExecuter workItemInsertExecuter = new WorkItemInsertExecuter(workItem);
		try {
			ExecuterManager.execute(connectionFactory, workItemInsertExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 作業項目情報を登録します。(週報登録ページ)
	 * 
	 * @param workItem 作業項目オブジェクト
	 * @throws DataUnavailableException
	 */
	public static void insertWeeklyReport(WorkItem workItem) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemWeeklyReportInsertExecuter workItemWeeklyReportInsertExecuter = new WorkItemWeeklyReportInsertExecuter(workItem);
		try {
			ExecuterManager.execute(connectionFactory, workItemWeeklyReportInsertExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 作業項目情報を削除します。
	 * 
	 * @param workItemId 作業項目ID
	 * @throws DataUnavailableException
	 */
	public static void delete(int workItemId) throws DataUnavailableException {

		ConnectionFactory connectionFactory = new ConnectionFactory();
		WorkItemDeleteExecuter workItemDeleteExecuter = new WorkItemDeleteExecuter(workItemId);

		try {
			ExecuterManager.execute(connectionFactory, workItemDeleteExecuter);
		} catch(SQLException sqle) {
			log.error(sqle.toString(), sqle);
			throw new DataUnavailableException(sqle.toString());
		}
	}

	/**
	 * 引数の作業項目の表示番号の作業項目オブジェクト
	 * と引数の作業項目の表示番号より1小さい作業項目
	 * オブジェクトをいれかえて作業項目オブジェクトの配列
	 * を返します。
	 *
	 * @param displayNm 作業項目の表示番号
	 * @param workItems 作業項目オブジェクトの配列
	 * @return 作業項目オブジェクトの配列
	 * @throws DataUnavailableException
	 */
	public static Vector getDownWorkItem(int displayNm,Vector workItems)
	 throws DataUnavailableException {

		WorkItem[] workItemList = (WorkItem[])workItems.toArray(new WorkItem[0]);
		Vector afterWorkItemList = new Vector();
		try {
			String change = null;
			for(int i=0;i<workItemList.length;i++){
				if(displayNm == workItemList[i].getDisplayNm() && change == null) {
					change = "OK";
					if((displayNm+1) < workItemList.length) {
						workItemList[i].setDisplayNm(displayNm+1);
						workItemList[i+1].setDisplayNm(displayNm);
					}
				}
				afterWorkItemList.add(workItemList[i]);
			}
		} catch(ArrayIndexOutOfBoundsException aioobe) {
			throw new DataUnavailableException(aioobe.toString());
		}

		return sortDisplayNm(afterWorkItemList);
	 }

	/**
	* 引数の作業項目の表示番号の作業項目オブジェクト
	* と引数の作業項目の表示番号より1大きい作業項目
	* オブジェクトをいれかえて作業項目オブジェクトの配列
	* を返します。
	*
	* @param displayNm 作業項目の表示番号
	* @param workItems 作業項目オブジェクトの配列
	* @return 作業項目オブジェクトの配列
	* @throws DataUnavailableException
	*/
	public static Vector getUpWorkItem(int displayNm,Vector workItems)
	 throws DataUnavailableException {

		WorkItem[] workItemList = (WorkItem[])workItems.toArray(new WorkItem[0]);
		Vector afterWorkItemList = new Vector();
		try {
			for(int i=0;i<workItemList.length;i++){
				if(displayNm == workItemList[i].getDisplayNm()) {
					if((displayNm - 1) >= 0) {
						workItemList[i-1].setDisplayNm(displayNm);
						workItemList[i].setDisplayNm(displayNm-1);
					}
				}
				afterWorkItemList.add(workItemList[i]);
			}
		} catch(ArrayIndexOutOfBoundsException aioobe) {
			throw new DataUnavailableException(aioobe.toString());
		}

		return sortDisplayNm(afterWorkItemList);
	 }

	public static Vector sortWorkItemList(Vector workItemList) {

		WorkItem[] workItem = (WorkItem[])workItemList.toArray(new WorkItem[0]);
		Vector sortProjectIdWorkItemList = new Vector();
		//プロジェクトＩＤでソート
		for (int i = 0; i < workItem.length; i++) {
			for (int j = i + 1; j < workItem.length; j++) {
				if(workItem[i].getProjectId() > workItem[j].getProjectId()){
					WorkItem tmpWorkItem = new WorkItem();
					tmpWorkItem = workItem[i];
					workItem[i] = workItem[j];
					workItem[j] = tmpWorkItem;
	
				}
			}
			sortProjectIdWorkItemList.add(workItem[i]);
		}

		Vector sortDisplayNmWorkItemList = new Vector();
		Vector sortWorkItemList = new Vector();
		WorkItem[] workItems = (WorkItem[])sortProjectIdWorkItemList.toArray(new WorkItem[0]);
		int projectId = 0;
		//表示番号でソート
		for(int i = 0;i < workItems.length;i++){
			if(projectId!=workItems[i].getProjectId()){
				Vector sortWorkItem = sortDisplayNm(sortDisplayNmWorkItemList);
				WorkItem[] items = (WorkItem[])sortWorkItem.toArray(new WorkItem[0]);
				for(int j = 0;j < items.length;j++){
					sortWorkItemList.add(items[j]);
				}
				sortDisplayNmWorkItemList = new Vector();
				sortDisplayNmWorkItemList.add(workItems[i]);
			}else{
				sortDisplayNmWorkItemList.add(workItems[i]);
			}
			if(i == (workItems.length - 1)){
				Vector sortWorkItem = sortDisplayNm(sortDisplayNmWorkItemList);
				WorkItem[] items = (WorkItem[])sortWorkItem.toArray(new WorkItem[0]);
				for(int j = 0;j < items.length;j++){
					sortWorkItemList.add(items[j]);
				}
			}
			projectId = workItems[i].getProjectId();
		}
		return sortWorkItemList;
	}

	public static Vector sortDisplayNm(Vector workItemList) {

		WorkItem[] workItem = (WorkItem[])workItemList.toArray(new WorkItem[0]);
		Vector newWorkItemList = new Vector();
		for (int i = 0; i < workItem.length; i++) {
			for (int j = i + 1; j < workItem.length; j++) {
				if(workItem[i].getDisplayNm() > workItem[j].getDisplayNm()){
					WorkItem tmpWorkItem = new WorkItem();
					tmpWorkItem = workItem[i];
					workItem[i] = workItem[j];
					workItem[j] = tmpWorkItem;
	
				}
			}
			newWorkItemList.add(workItem[i]);
		}
		return newWorkItemList;
	}

}